# -*- coding:utf8 -*-

import arcpy
import os
import json
import urllib2
import arcpy

import sys
reload(sys)
sys.setdefaultencoding('utf8')

import time
from functools import wraps
def retry(ExceptionToCheck, tries=4, delay=1, backoff=2, logger=None):
    def deco_retry(f):

        @wraps(f)
        def f_retry(*args, **kwargs):
            mtries, mdelay = tries, delay
            while mtries > 1:
                try:
                    return f(*args, **kwargs)
                except ExceptionToCheck, e:
                    msg = "%s, Retrying in %d seconds..." % (str(e), mdelay)
                    if logger:
                        logger.warning(msg)
                    else:
                        arcpy.AddWarning(msg)
                    time.sleep(mdelay)
                    mtries -= 1
                    mdelay *= backoff
            return f(*args, **kwargs)

        return f_retry

    return deco_retry

access_token="1MNrcRmU3mZgCuKgHukfIt9XF2GblvcC"


@retry(Exception)
def request(uri, **kvargs):
    if 'ak' not in kvargs: kvargs['ak'] = access_token
    url = '{}{}{}'.format(uri,
                          '&' if '?' in uri else '?',
                          '&'.join('{}={}'.format(k, kvargs[k]) for k in kvargs))
    content = urllib2.urlopen(url).read()
    result = json.loads(content)
    if result['status'] == 0:
        return result['result']
    else:
        raise urllib2.URLError(result['status'])

def concat(coords):
    if isinstance(coords[0], (list, tuple)):
        return ';'.join(concat(c) for c in coords)
    else:
        return ','.join(str(c) for c in coords)

def convert(coords, ak = None, reverse = False):
    uri_base = "http://api.map.baidu.com/geoconv/v1/"
    #if ak is None: ak = access_token
    chunk = 100
    coords = [coords[i:i+chunk] for i in range(0, len(coords), chunk)]
    result = []
    for c in coords:
        #uri = "{}?coords={}&ak={}".format(uri_base, concat(c), ak)
        #result.extend(request(uri))
        if reverse:
            res = request(uri_base+"?from=3", coords=concat(c))
            result.extend((2*coords[i][0]-r['x'],2*coords[i][1]-r['y']) for i,r in enumerate(res))
        else:
            res = request(uri_base, coords=concat(c))
            result.extend((r['x'],r['y']) for r in res)
    return result

def transformFeature(dataset):
    cursor = arcpy.da.UpdateCursor(dataset,["shape@", 'oid@'])
    for row in cursor:
        arcpy.AddMessage('Transform Feature: {}'.format(row[1]))
        row[0] = transformGeometry(row[0])
        cursor.updateRow(row)
    del cursor

def transformGeometry(geometry):
    supportType = ['polygon', 'polyline', 'point', 'multipoint']
    if not geometry.type in supportType:
        raise Exception('Unsupport geometry type')
    supportSP = ['GCS_WGS_1984','GCS_China_Geodetic_Coordinate_System_2000']
    if not geometry.spatialReference.GCSName in supportSP:
        raise Exception('Unsupport spatial reference')
    if geometry.type == 'point':
        point = geometry.getPart(0)
        trans = convert((point.X, point.Y))
        return arcpy.Point(*trans[0])
    partNum = 0
    partCount = geometry.partCount
    array = arcpy.Array()
    while partNum < partCount:
        part = geometry.getPart(partNum)
        holes = []
        coords = []
        for i, point in enumerate(part):
            if point is None:
                holes.append(i)
            else:
                coords.append((point.X, point.Y))
        partArray = arcpy.Array()
        trans = convert(coords)
        arcpy.AddMessage('Convert {} Points.'.format(len(trans)))
        for point in trans:
            partArray.add(arcpy.Point(*point))
        for i in holes:
            partArray.insert(i, None)
        array.add(partArray)
        partNum += 1
    if geometry.type == 'polygon':
        return arcpy.Polygon(array, geometry.spatialReference)
    elif geometry.type == 'polyline':
        return arcpy.Polyline(array, geometry.spatialReference)
    elif  geometry.type == 'multipoint':
        return arcpy.Multipoint(array, geometry.spatialReference)
    return geometry

def test():
    inFeature = r'3709村级边界.shp'
    outFeature = r'Geodatabase.gdb\village0'
    arcpy.Delete_management(outFeature)
    arcpy.CopyFeatures_management(inFeature, outFeature)
    transformFeature(outFeature)

if __name__ == '__main__':
    inFeature = arcpy.GetParameter(0)
    outFeature = arcpy.GetParameter(1)
    if not arcpy.Exists(inFeature):
        raise Exception('In feature not exists')
    if arcpy.Exists(outFeature):
        arcpy.Delete_management(outFeature)
    arcpy.CopyFeatures_management(inFeature, outFeature)
    transformFeature(outFeature)
